SWAGOLX.EXE (c) 1993 GDSOFT ALL RIGHTS RESERVED 00023 KEYBOARD I/O ROUTINES 1 05-28-9313:49ALL SWAG SUPPORT TEAM Stuff Keyboard Buffer IMPORT 19 {πROB PERELMANππ> I want to put the character and scan code for ALT-V in the keyboard buffer.π> In fact I would like to put it in there twice. I need it to be in theπ> buffer so that when my program terminates the parent process will act onπ> that key.ππ{π If this is being used with Turbo Pascal Version 3.0, you MUST setπ the C and U compiler directives to MINUS!π If this is being used with Turbo Pascal Version 4.0, then set theπ CheckBreak variable of the CRT unit to FALSE!π}ππUsesπ Crt;ππTypeπ BufType = Array[30..62] of Byte;ππVarπ Head : Integer Absolute $0000 : $041A; { Location of head of buffer }π Tail : Integer Absolute $0000 : $041C; { Location of tail of buffer }π KBDBuf : BufType absolute $0000 : $041E; { Absolute location of buffer }π S : String[80]; { Input string }ππProcedure StufftheBuff (Ch : Char; Code : Byte);πVarπ TempTail : Integer; { Temporary holding of Tail }πBeginπ TempTail := Tail; { Store the Temporary Tail }π Tail := Tail + 2; { Incriment Tail to next pos }π If Head = Tail Then { Is the buffer full? }π Beginπ Tail := TempTail; { Reset to previos value }π Sound(440); { Beep the user }π Delay(400); { Delay for the beep }π NoSound; { Turn off the sound }π Endπ Elseπ Beginπ KBDBuf[TempTail] := Ord(Ch); { Put the ASCII value in buf }π KBDBuf[TempTail + 1] := Code; { Put extended keypress valu }π If Tail > 60 then { Last position. Wrap? }π Tail := 30; { Wrap to 1st position }π End;πEnd;ππBeginπ ClrScr; { Clear the Screen }π StufftheBuff ( 'D',0 ); { Start stuffing the buffer }π StufftheBuff ( 'I',0 ); { Another stuff of the Buffer}π StufftheBuff ( 'R',0 ); { " " " " " }π StufftheBuff ( #13,0 ); { CR } { Stuff a carriage return }πEnd.π 2 05-28-9313:49ALL SWAG SUPPORT TEAM Clear Keyboard Buffer IMPORT 8 {πEDWIN CALIMBOππ║ I need to know how I can clear the keyboard buffer.π║ The reason I need to do this is that in a loop I'm reading inπ║ one Character and then calling a Procedure which returns to theπ║ loop For the next Character to be read. But sometimes it takes theπ║ next Character in the buffer that my have been a result of just holdingπ║ down a key For to long.πππ You can clear any keys in the keyboard buffer by using the following loop:π}π While KeyPressed Doπ ch := ReadKey;π{π Another way to clear the keyboard buffer is to set the keyboard headπ equal to the keyboard tail and the keyboard buffer as a circular buffer.π You can set the tail equal to the head this way:π}π MemW[$0000:$041C] := MemW[$0000:$041A]; { flush keyboard buffer }π 3 05-28-9313:49ALL SWAG SUPPORT TEAM INT09 Keyboard handler #1IMPORT 21 {π> Does anybody know of a way to reWrite the keyboard routines, to be ablπ> to read several keys at once? ReadKey will only read the last keypressπ> anything else I've tried can only read the last key you have pressed dπ>π> For example, in many games it will let you move Forward (With the Forwπ> arrow key) and shoot at the same time, With the space bar...Any suggesπ}ππUnit POLL ; { polled keyboard handler }π { does not support F11 or F12 keys } InterfaceππConstπ EscKey = 1 ; { key codes }π aKey = 30 ; { see TP 6 Programmers guide p 354 }π sKey = 31 ;π endKey = 79 ;π DownKey = 80 ;ππVarπ KeyTable : Array[ 1..127 ] of Boolean ; { KeyTable[ x ] is True when key xπis pressed } { and stays True Until key x is released }ππImplementationππUses Dos, KeyIntr ; { keyboard interrupt support }ππVarπ OldInt09 : Pointer ;π ExitSave : Pointer ;ππ{$F+} Procedure RestoreInt09 ;πbeginπ ExitProc := ExitSave ;π SetIntVec( $09, OldInt09 ) ;πend ;ππ{$F+} Procedure NewInt09 ; interrupt ;πVarπ ScanCode : Byte ;π KeyCode : Byte ;πbeginπ STI ;π ScanCode := ReadScanCode ;π KeyCode := ScanCode and $7F ; { strip make/break bit }π KeyTable[ KeyCode ] := ( ScanCode and $80 ) = 0 ; (* { For non C Programmersπ}π if ( ScanCode and $80 ) = 0 then { make code -- key pressed }π KeyTable[ KeyCode ] := Trueπ else { break code -- key released }π KeyTable[ KeyCode ] := False ;π*)π ResetKeyboard ;π EOI ;πend ;ππVarπ N : Byte ;ππbeginπ ExitSave := ExitProc ;π ExitProc := addr( RestoreInt09 ) ;ππ For N := 1 to 127 do { no key pressed }π KeyTable[ N ] := False ;ππ GetIntVec( $09, OldInt09 ) ;π SetIntVec( $09, addr( NewInt09 ) ) ;πend.π{---------------------------------------------} Program TwoKeys;ππUses Crt, Poll ; { polled keyboard handler } { ----- this Program willπprobably hang a debugger ----- } Varπ X, Y : Byte ;πbeginπ ClrScr ;π X := 40 ;π Y := 12 ;ππ WriteLn( 'Hit keys A S and 1 2 on the keypad' ) ;π WriteLn( ' -- Esc to stop' ) ;ππ While not KeyTable[ EscKey ] doπ beginπ GotoXY( X, Y ) ;π Write( ' ' ) ;ππ{ poll the KeyTable }π if KeyTable[ endKey ] and ( X > 1 ) then Dec( X ) ;π if KeyTable[ DownKey ] and ( X < 80 ) then Inc( X ) ;π if KeyTable[ aKey ] and ( Y > 4 ) then Dec( Y ) ;π if KeyTable[ sKey ] and ( Y < 24 ) then Inc( Y ) ;ππ GotoXY( X, Y ) ;π Write( chr( 1 ) ) ;π Delay( 10 ) ;π end ;πend.π 4 05-28-9313:49ALL SWAG SUPPORT TEAM INT09 Keyboard handler #2IMPORT 29 {πHere is my source For the keyboard handler.π}ππ{$X+}ππUnit KbIO;ππ(*---------------------------*) Interface (*----------------------------*)ππUses Dos;ππVarπ KbScancode : Byte; { internal Variable, can be used by host Program }π OldInt9Vect : Pointer; { For storing the old interrupt vector }ππProcedure RestoreOldInt9;πProcedure NewInt9; Interrupt;ππ(*------------------------*) Implementation (*--------------------------*)ππProcedure RestoreOldInt9; { Restores control to the old interrupt handler }πbeginπ SetIntVec($09, OldInt9Vect);πend;ππ{$F+}πProcedure NewInt9; (* Interrupt; *)πVarπ scancode : Byte;ππ Procedure ResetKBD;π Varπ b : Byte;π beginπ b := Port[$61];π Port[$61] := b or $80;π Port[$61] := b;π Port[$20] := $20;π end;ππbeginπ scancode := Port[$60];π KbScancode := scancode;π (* at this point, you could add Up, Down, Left & Right Varsπ eg. if (KbScancode = 72) then Up := True;π if (KbScancode = 72 + 128) then Up := False;π .π .π .π Don't Forget to initialize Up, Down, etc. if you use them! *)π ResetKBD;πend;π{$F-}ππbeginπ GetIntVec($09, OldInt9Vect);π SetIntVec($09, @NewInt9);π KbScancode := 0;π (*π At this point, the Unit could install a custom Exit Procedureπ that automatically restores the old keyboard handler when theπ host Program finishes.π *)πend.ππ{πJust include this Unit in your Uses clause, and, at any time during yourπProgram, you can check 'KbScancode' to see which key was currently pressed orπreleased. Pressed keys have values between 0..127, and released keys have aπvalue between 128..255. ESC = scancode #1, so here's a sample.π}πFunction Check4Quit : Boolean;πVarπ kbcode : Byte;π tmpBool : Boolean;πbeginπ tmpBool := False;π kbcode := KbScancode;π if (kbcode = 1) thenπ beginππ Repeatπ kbcode := KbScancodeπ Until (kbcode <> 1);π (* the above line Repeats Until a different key is pressedπ or released *)ππ if (kbcode = 129) thenπ tmpBool := True;π (* if they released ESC directly after pressing it, withoutπ pressing or releasing any other keys, return a True value *)ππ end;π Check4Quit := tmpBool;πend;ππ{πSo, basically, it's a good idea to save KbScancode in a temporary VariableπbeFore doing any checks on it, as it may change if you do this:ππif (KbScancode = 1) then beginπ Delay(1);π WriteLn('You pressed key #', KbScancode);πend;ππIn that short Delay, they may have released the key or pressed a new one,so theπvalue would have changed, and the Program might screw up.ππSomething to add: Boolean Variables For Up, Down, Left, and Right, For use inπgames and such. See the section in Procedure NewInt9.πππHey, Drew. I Forgot one thing in my message about the custom KB handler.πYou'll probably receive this message at the same time as the Unit I sent.πHere is the important message:ππWhen using the KbIO Unit, at the very end of your Program, include the lineπthat restores the old int9 vector. It is a Procedure called 'RestoreOldInt9'.πIt may not be Absolutely essential to include this line, but if you don'tπrestore the old keyboard handler, you might not be able to Type anything whenπthe Program Exits! (not so good, huh?) What to do: you can install a customπexit Procedure that restores the old int9 vector. if you don't know how to doπthis, quote these lines, or Write to me about "custom Exit Procedures toπrestore the old int9 vector," or something like that. Bye For now.π}π 5 05-28-9313:49ALL SWAG SUPPORT TEAM INT09 Keyboard handler #3IMPORT 30 {π> Does anybody know of a way to reWrite the keyboard routines, to be ablπ> to read several keys at once? ReadKey will only read the last keypressπ> anything else I've tried can only read the last key you have pressed dπ>π> For example, in many games it will let you move Forward (With the Forwπ> arrow key) and shoot at the same time, With the space bar...Any suggesπOops, I Forgot to include one of the Units you'll need to do this. I've alreadyπsent you POLL.PAS and TWOKEYS.PAS. Here's KEYinTR.PAS:π}πUnit KeyIntr ; { support For inT 09 routines } { Turbo Pascal 5.5 } InterfaceπProcedure CLI ; Inline( $FA ) ; { disable interrupts } Procedure STI ;πInline( $FB ) ; { enable interrupts } { cannot be used outside an interruptπProcedure } Procedure JumpInterrupt( p : Pointer ) ; { see TP5 Ref p 222π} Inline( $5B/$58/ { POP BX, AX AX:BX = p }π $89/$EC/ { MOV SP, BP }π $87/$46/$10/ { XCHG AX, [BP+10H] }π $87/$5E/$0E/ { XCHG BX, [BP+0EH] }π $5D/$07/$1F/$5F/$5E/ { POP BP, ES, DS, DI, SI }π $5A/$59/ { POP DX, CX }π $FA/ { CLI }π $CB ) ; { RETF jmp Far p }ππFunction Control_Pressed : Boolean ;πProcedure EOI ; { end of interrupt to 8259 } FunctionπReadScanCode : Byte ; { read keyboard } Procedure ResetKeyboard ;π { prepare For next key } Procedure StoreKey( Scan, Key : Byte )π;π { put key in buffer For inT 16 }πImplementation Uses Crt ; { Sound, NoSound } Typeπ Address = Record { used in Pointer manipulation }π offset : Word ;π Segment : Word ;π end ;πConstπ BiosDataSegment = $40 ;πVarπ KeyState : Word Absolute BiosDataSegment:$0017 ;π KeyBufferHead : Word Absolute BiosDataSegment:$001A ;π KeyBufferTail : Word Absolute BiosDataSegment:$001C ;π KeyBufferStart : Word Absolute BiosDataSegment:$0080 ;π KeyBufferend : Word Absolute BiosDataSegment:$0082 ;πππFunction Control_Pressed : Boolean ;πbeginπControl_Pressed := ( KeyState and 4 ) = 4 ; end ;ππProcedure EOI ; { end of interrupt to 8259 interrupt controller } beginπ CLI ;π Port[$20] := $20 ; { see TP5 ref p 211 } end ;ππFunction ReadScanCode : Byte ;πbeginπReadScanCode := Port[$60] ;πend ;ππProcedure ResetKeyboard ; { prepare For next key } Varπ N : Byte ;πbeginπ N := Port[$61] ;π Port[$61] := ( N or $80 ) ;π Port[$61] := N ;πend ;ππProcedure StoreKey( Scan, Key : Byte ) ; Var { put key in bufferπthat inT 16 reads }π P : ^Word ;π N : Word ;πbeginπ address(P).segment := BiosDataSegment ;π N := KeyBufferTail ;π address(P).offset := N ;π Inc( N, 2 ) ; { advance Pointer two Bytes }π if( N = KeyBufferend ) then { end of the circular buffer }π N := KeyBufferStart ;π if( N = KeyBufferHead ) then { buffer full }π beginπ EOI ; { EOI must be done beFore Exit }π Sound( 2200 ) ; { but beFore anything that takes a lot }π Delay( 80 ) ; { of time and can be interrupted }π NoSound ;π endπ elseπ begin { high Byte is scan code, low is ASCII }π P^ := Scan * $100 + Key ; { store key in circular buffer }π KeyBufferTail := N ; { advance tail Pointer }π EOI ;π end ;πend ;πend.π 6 05-28-9313:49ALL SWAG SUPPORT TEAM Turn Keyboard OFF IMPORT 15 {IDIOT PASCAL 101π----------------ππWelcome to IP 101. In today's lesson we will be answering a fewπoften asked questions about Turbo Pascal. if you signed up ForπIDIOT C/C++ 101, please get up and run beFore you get shot.ππQ: HOW do I TURN ofF/ON THE KEYBOARD FROM MY Program?πA: Easy. Though you may search through many books, you will findπ the answer in a Excellent reference called _THE MS-Dosπ ENCYCLOPEDIA_. It tells of a mystical I/O port where you canπ turn off/on the keyboard by just flipping a bit. This port isπ the 8259 Programmible Interrupt Controller. Now, part of theπ 8259 is the Interrupt Mask Register, or IMR For short. Theπ port location is $21. to turn off the Keyboard...(RECKLESSLY)ππ} Procedure KEYBOARD_ofF;ππ beginπ PorT[$21]:=$02π end;π{π to turn the keyboard back on (RECKLESSLY), just set the portπ back to $0.ππ (THE MSDos ENCYCLOPEDIA (C) 1988 Microsoft Press p417)ππQ: HOW do I FLIP BITS ON/ofF in A Byte or Integer?πA: Simple, Really. The following Procedures work on bothπ Byte,Char,Boolean,Integer, and Word values(I hope).π}πProcedure SBIT(Var TARGET;BITNUM:Integer); {set bit}ππVarπ SUBJECT : Integer Absolute TARGET;π MASK : Integer;ππ beginπ MASK := 1 SHL BITNUM;π SUBJECT := SUBJECT or MASKπ end;ππProcedure CBIT(Var TARGET;BITNUM:Integer); {clear bit}ππ Varπ SUBJECT : Integer Absolute TARGET;π MASK : Integer;ππ beginπ MASK := not(1 SHL BITNUM);π SUBJECT := SUBJECT and MASKπ end;ππProcedure SETBIT(Var TARGET;BITNUM:Integer;VALUE:Byte);{control}π {Proc. }π beginπ if VALUE = 1 thenπ SBIT(TARGET,BITNUM)π elseπ CBIT(TARGET,BITNUM)π end;ππ 7 05-28-9313:49ALL SWAG SUPPORT TEAM Keyboard Handler IMPORT 43 {π> I need help on reading the keyboard in a specific way, I need toπ> read it as a whole not a key at a time. I need to do this forπ> the games I make, I have to ba able to hold down one key toπ> perform a Function and then hold down another key and scan bothπ> keys at the same time but to perform 2 different Functions. Forπ> instance, if I hold down the left arrow key to make a Characterπ> run I should be able to hold down the space bar to make himπ> fire a gun at the same time.π> I would Really appreciate any help anyone could give me With this.ππGrab this (TWOKEYS.PAS) and the next 2 messages (KEYINTR.PAS and POLL.PAS).π}ππProgram TwoKeys;ππUsesπ Crt, Poll ; { polled keyboard handler }ππ{ ----- this Program will probably hang a debugger ----- }ππVarπ X, Y : Byte ;ππbeginπ ClrScr ;π X := 40 ;π Y := 12 ;ππ WriteLn( 'Hit keys A S and 1 2 on the keypad' ) ;π WriteLn( ' -- Esc to stop' ) ;ππ While not KeyTable[ EscKey ] doπ beginπ GotoXY( X, Y ) ;π Write( ' ' ) ;ππ { poll the KeyTable }π If KeyTable[ endKey ] and ( X > 1 ) then Dec( X ) ;π If KeyTable[ DownKey ] and ( X < 80 ) then Inc( X ) ;π If KeyTable[ aKey ] and ( Y > 4 ) then Dec( Y ) ;π If KeyTable[ sKey ] and ( Y < 24 ) then Inc( Y ) ;ππ GotoXY( X, Y ) ;π Write( chr( 1 ) ) ;π Delay( 10 ) ;π end ;πend.πππππUnit KeyIntr ; { support For INT 09 routines }ππInterfaceππProcedure CLI ; Inline( $FA ) ; { disable interrupts }πProcedure STI ; Inline( $FB ) ; { enable interrupts }ππ{ cannot be used outside an interrupt Procedure }πProcedure JumpInterrupt( p : Pointer ) ;πInline(π $5B/$58/ { POP BX, AX AX:BX = p }π $89/$EC/ { MOV SP, BP }π $87/$46/$10/ { XCHG AX, [BP+10H] }π $87/$5E/$0E/ { XCHG BX, [BP+0EH] }π $5D/$07/$1F/$5F/$5E/ { POP BP, ES, DS, DI, SI }π $5A/$59/ { POP DX, CX }π $FA/ { CLI }π $CB ) ; { RETF jmp far p }πππFunction Control_Pressed : Boolean ;ππProcedure EOI ;π{ end of interrupt to 8259 }ππFunction ReadScanCode : Byte ;π{ read keyboard }ππProcedure ResetKeyboard ;π{ prepare For next key }ππProcedure StoreKey( Scan, Key : Byte );π{ put key in buffer For INT 16 }πππImplementationππUsesπ Crt ; { Sound, NoSound }ππTypeπ Address = Record { used in Pointer manipulation }π Offset : Word ;π Segment : Word ;π end ;πConstπ BiosDataSegment = $40 ;ππVarπ KeyState : Word Absolute BiosDataSegment:$0017 ;π KeyBufferHead : Word Absolute BiosDataSegment:$001A ;π KeyBufferTail : Word Absolute BiosDataSegment:$001C ;π KeyBufferStart : Word Absolute BiosDataSegment:$0080 ;π KeyBufferend : Word Absolute BiosDataSegment:$0082 ;πππFunction Control_Pressed : Boolean ;πbeginπ Control_Pressed := ( KeyState and 4 ) = 4 ;πend;ππProcedure EOI ;π{ end of interrupt to 8259 interrupt controller }πbeginπ CLI ;π Port[$20] := $20 ;πend ;ππFunction ReadScanCode : Byte ;πbeginπ ReadScanCode := Port[$60] ;πend ;ππProcedure ResetKeyboard ;π{ prepare For next key }πVarπ N : Byte ;πbeginπ N := Port[$61] ;π Port[$61] := ( N or $80 ) ;π Port[$61] := N ;πend ;ππProcedure StoreKey( Scan, Key : Byte ) ;πVarπ{ put key in buffer that INT 16 reads }π P : ^Word ;π N : Word ;πbeginπ address(P).segment := BiosDataSegment ;π N := KeyBufferTail ;π address(P).offset := N ;π Inc( N, 2 ) ; { advance Pointer two Bytes }π If( N = KeyBufferend ) then { end of the circular buffer }π N := KeyBufferStart ;π If( N = KeyBufferHead ) then { buffer full }π beginπ EOI ; { EOI must be done before Exit }π Sound( 2200 ) ; { but before anything that takes a lot }π Delay( 80 ) ; { of time and can be interrupted }π NoSound ;π endπ Elseπ begin { high Byte is scan code, low is ASCII }π P^ := Scan * $100 + Key ; { store key in circular buffer }π KeyBufferTail := N ; { advance tail Pointer }π EOI ;π end ;πend ;ππend.πππππUnit POLL ; { polled keyboard handler }π { does not support F11 or F12 keys } InterfaceππConstπ EscKey = 1 ; { key codes }π aKey = 30 ;π sKey = 31 ;π endKey = 79 ;π DownKey = 80 ;ππVarπ KeyTable : Array[ 1..127 ] of Boolean ;ππ{ KeyTable[ x ] is True when key x is pressed and stays True Until keyπ x is released }πππImplementationππUsesπ Dos, KeyIntr ; { keyboard interrupt support }ππVarπ OldInt09 : Pointer ;π ExitSave : Pointer ;ππProcedure RestoreInt09 ; Far;πbeginπ ExitProc := ExitSave ;π SetIntVec( $09, OldInt09 ) ;πend ;ππProcedure NewInt09 ; interrupt ; Far;πVarπ ScanCode : Byte ;π KeyCode : Byte ;πbeginπ STI ;π ScanCode := ReadScanCode ;π KeyCode := ScanCode and $7F ; { strip make/break bit }π KeyTable[ KeyCode ] := ( ScanCode and $80 ) = 0 ;π ResetKeyboard ;π EOI ;πend ;ππVarπ N : Byte ;ππbeginπ ExitSave := ExitProc ;π ExitProc := addr( RestoreInt09 ) ;ππ For N := 1 to 127 do { no key pressed }π KeyTable[ N ] := False ;ππ GetIntVec( $09, OldInt09 ) ;π SetIntVec( $09, addr( NewInt09 ) ) ;πend.π 8 05-28-9313:49ALL SWAG SUPPORT TEAM Get Keyboard CLICK IMPORT 8 {$M $800,0,0 } { 2K stack, no heap }π{ This Program caUses a click each timeπ a key is pressed.}πUses Crt, Dos;πVarπ KbdIntVec : Procedure;π{$F+}πProcedure Keyclick; interrupt;πbeginπ if Port[$60] < $80 thenπ { Only click when key is pressed }π beginπ Sound(5000);π Delay(1);π NoSound;π end;π Inline ($9C); { PUSHF -- Push flags }π { Call old ISR using saved vector }π KbdIntVec;πend;π{$F-}πbeginπ { Insert ISR into keyboard chain }π GetIntVec($9,@KbdIntVec);π SetIntVec($9,Addr(Keyclick));π Keep(0); { Terminate, stay resident }π readln;πend.ππ{πActually this works as long as you change the GETinTVEC line, where it saysπ@@KbdIntVec, it should be only one @, odd that borland would have an exampleπthat didn't Compile. (It's a fine example, surprised myself too)π} 9 05-28-9313:49ALL SWAG SUPPORT TEAM Int 09 Support IMPORT 22 UNIT KeyIntr ; { support for INT 09 16 routines } { Turbo Pascal 5.5+ }ππINTERFACEππTypeπ InterruptProcedure = Procedure ;ππConstπ BiosDataSegment = $40 ;ππProcedure DisableInterrupts ; Inline( $FA ) ; { CLI }πProcedure EnableInterrupts ; Inline( $FB ) ; { STI }πProcedure CallInterrupt( P : Pointer ) ;ππFunction AltPressed : Boolean ;πFunction ControlPressed : Boolean ;πFunction ShiftPressed : Boolean ;ππProcedure EOI ; { end of interrupt to 8259 }πFunction ReadScanCode : Byte ; { read keyboard }πProcedure ResetKeyboard ; { prepare for next key }π { put key in buffer for INT 16 }πFunction StoreKey( Scan, Key : Byte ) : Boolean ;ππIMPLEMENTATIONππTypeπ TwoBytesPtr = ^TwoBytes ;π TwoBytes = { one key in the keyboard buffer }π Recordπ KeyCode,π ScanCode : Byte ;π End ;ππVarπ KeyState : Word Absolute BiosDataSegment:$17 ;π KeyBufferHead : Word Absolute BiosDataSegment:$1A ;π KeyBufferTail : Word Absolute BiosDataSegment:$1C ;π KeyBufferStart : Word Absolute BiosDataSegment:$80 ;π KeyBufferEnd : Word Absolute BiosDataSegment:$82 ;ππProcedure CallInterrupt( P : Pointer ) ;πBeginπ Inline( $9C ) ; { PUSHF }π InterruptProcedure(P) ;πEnd ;ππFunction AltPressed : Boolean ;πBeginπ AltPressed := (KeyState and 8) <> 0 ;πEnd ;ππFunction ControlPressed : Boolean ;πBeginπ ControlPressed := (KeyState and 4) <> 0 ;πEnd ;ππFunction ShiftPressed : Boolean ;πBeginπ ShiftPressed := (KeyState and 3) <> 0 ;πEnd ;ππProcedure EOI ; { end of interrupt to 8259 interrupt controller }πBeginπ Port[$20] := $20 ;πEnd ;ππFunction ReadScanCode : Byte ;πVarπ N : Byte ;πBeginπ N := Port[$60] ; { $FF means keyboard overrun }π ReadScanCode := N ;πEnd ;ππProcedure ResetKeyboard ; { prepare for next key }πVarπ N : Byte ;πBeginπ N := Port[$61] ;π Port[$61] := (N or $80) ;π Port[$61] := N ;πEnd ;ππFunction StoreKey( Scan, Key : Byte ) : Boolean ;πVar { put key in buffer that INT 16 reads }π P : TwoBytesPtr ;π N : Word ;πBeginπ DisableInterrupts ;ππ N := KeyBufferTail ;π P := Ptr( BiosDataSegment, N ) ;ππ Inc( N, 2 ) ;π If( N = KeyBufferEnd ) then { end of the circular buffer }π N := KeyBufferStart ;π If( N = KeyBufferHead ) then { buffer full }π Beginπ EnableInterrupts ;π StoreKey := False ;π Endπ Elseπ Beginπ P^.KeyCode := Key ;π P^.ScanCode := Scan ; { store key in circular buffer }π KeyBufferTail := N ; { advance tail pointer }π EnableInterrupts ;π StoreKey := True ;π End ;πEnd ;πππEND.ππππ 10 05-28-9313:49ALL SWAG SUPPORT TEAM Keyboard SCAN Keys IMPORT 28 {π> I need help on reading the keyboard in a specific way, I need to read itπ>as a whole not a key at a time. I need to do this For the games I make, Ihaπ>to ba able to hold down one key to perform a Function and then hold downπ>another key and scan both keys at the same time but to perform 2 differentπ>Functions. For instance, if I hold down the left arrow key to make aCharactπ>run I should be able to hold down the space bar to make him fire agun at thπ>same time.ππ by Sean Palmer, 1993, released to public domainπ}ππUnit keyScan; {for now, ignores extended codes ($E0 prefix)}ππInterfaceππTypeπ scanCode = (π kNone, kEsc, k1, k2, k3, k4, k5, k6, k7, k8, k9, k0, kMinus, kEqual,π kBack, kTab, kQ, kW, kE, kR, kT, kY, kU, kI, kO, kP, kLBracket,π kRBracket, kEnter, kCtrl, kA, kS, kD, kF, kG, kH, kJ, kK, kL, kColon,π kQuote, kTilde, kLShift, kBackSlash, kZ, kX, kC, kV, kB, kN, kM, kComma,π kPeriod, kSlash, kRShift, kPadStar, kAlt, kSpace, kCaps, kF1, kF2, kF3,π kF4, kF5, kF6, kF7, kF8, kF9, kF10, kNum, kScroll, kHome, kUp, kPgUp,π kPadMinus, kLf, kPad5, kRt, kPadPlus, kend, kDn, kPgDn, kIns, kDel,π kSysReq, kUnknown55, kUnknown56, kF11, kF12);ππConstπ kPad7 = kHome;π kPad8 = kUp;π kPad9 = kPgUp;π kPad4 = kLf;π kPad6 = kRt;π kPad1 = kend;π kPad2 = kDn;π kPad3 = kPgDn;π letters = [kQ..kP, kA..kL, kZ..kM];π numbers = [k1..k0, kPad1..kPad3, kPad4..kPad6, kPad7..kPad9];π FunctionKeys = [kF1..kF10, kF11..kF12];π keyPad = [kPadStar, kNum..kDel];ππVarπ keyboard : set of scanCode;π lastKeyDown : scanCode;ππImplementationπUses Dos;ππConstπ normChar : Array [scanCode] of Char = (π {00} #0,^[,'1','2','3','4','5','6','7','8','9','0','-','=',^H,^I,π {10} 'q','w','e','r','t','y','u','i','o','p','[',']',^M,#0,'a','s',π {20} 'd','f','g','h','j','k','l',';','''','`',#0,'\','z','x','c','v',π {30} 'b','n','m',',','.','/',#0,'*',#0,' ',#0,#0,#0,#0,#0,#0,π {40} #0,#0,#0,#0,#0,#0,#0,'7','8','9','-','4','5','6','+','1',π {50} '2','3','0','.',#0,#0,#0,#0,#0);π shiftChar : Array [scanCode] of Char = (π {00} #0,^[,'!','@','#','$','%','^','&','*','(',')','_','+',^H,^I,π {10} 'Q','W','E','R','T','Y','U','I','O','P','{','}',^M,#0,'A','S',π {20} 'D','F','G','H','J','K','L',':','"','~',#0,'|','Z','X','C','V',π {30} 'B','N','M','<','>','?',#0,'*',#0,' ',#0,#0,#0,#0,#0,#0,π {40} #0,#0,#0,#0,#0,#0,#0,'7','8','9','-','4','5','6','+','1',π {50} '2','3','0','.',#0,#0,#0,#0,#0);ππFunction ascii(k : scanCode) : Char;πbeginπ if [kLShift, kRShift] * keyboard <> [] thenπ ascii := shiftChar[k]π elseπ ascii := normChar[k];πend;ππVarπ oldKeyInt : Pointer;ππProcedure keyISR; interrupt;πVarπ k : scanCode;π b : Byte;πbeginπ Asmπ in al, $60;π mov b, al;π and al, $7F;π mov k, al;π pushF;π call [oldKeyInt]; {allow BIOS to process also}π end;π memW[$40 : $1A] := memW[$40 : $1C]; {clear BIOS keyboard buffer}π if shortint(b) >= 0 thenπ beginπ keyboard := keyboard + [k];π lastKeyDown := k;π endπ elseπ if b <> $E0 thenπ keyboard := keyboard - [k]π else ;πend;ππProcedure keybegin;πbeginπ keyboard := [];π lastKeyDown := kNone;π getIntVec(9, oldKeyInt);π setIntVec(9, @KeyISR);πend;ππVarπ ExitSave:Pointer;ππProcedure keyend;πbeginπ setIntVec(9, oldKeyInt);π ExitProc := ExitSave;πend;πππbeginπ keybegin;π ExitSave := ExitProc;π ExitProc := @keyend;πend.π 11 05-28-9313:49ALL SWAG SUPPORT TEAM Lock Keyboard IMPORT 14 {$X+}ππ{ Author Trevor J Carlsen. Released into the public domain. Req TP6 }π{ Compile and run this Program and all keyboard input except keys that }π{ make up a valid passWord will be ignored. In this Case the passWord }π{ is '1234' and the scancodes For those keys are stored in a Constant. }π{ to change the passWord Compute the scancodes For the desired passWord}π{ and change the passWord approriately. }ππUsesπ Dos,π Crt;ππVarπ OldInt9 : Pointer; { For storing the old interrupt vector }π passWord : String[4];π pwdlen : Byte Absolute passWord;π πProcedure RestoreOldInt9;π { Restores control to the old interrupt handler }π beginπ SetIntVec($09,OldInt9);π end;ππ{$F+}πProcedure NewInt9; interrupt;π π Constπ masterpwd :String[4] = #2#3#4#5; { '1234' scancodes }π Var π scancode : Byte;ππ Procedure ResetKBD;π Varπ b : Byte;π beginπ b := port[$61]; π port[$61] := b or $80;π port[$61] := b;π port[$20] := $20; { Signals EOI to PIC }π end;π πbeginπ scancode := port[$60]; π if chr(scancode) = masterpwd[pwdlen+1] then beginπ passWord[pwdlen+1] := chr(scancode);π inc(pwdlen);π if passWord = masterpwd thenπ RestoreOldInt9;π endπ else if not odd(scancode shr 7) then { invalid key }π pwdlen := 0;π ResetKBD;πend; π{$F-}ππbeginπ pwdlen := 0;π GetIntVec($09,OldInt9);π SetIntVec($09,@NewInt9);π ReadKey;πend. π π πππTeeCeeπππ--- TC-ED v2.01 π * origin: The Pilbara's Pascal Centre (+61 91 732569) (3:690/644)ππ 12 05-28-9313:49ALL SWAG SUPPORT TEAM Read CTRL/ALT/SHIFT Keys IMPORT 11 {π> I was sitting here thinking about how usefull it would be to be ableπ> to check the status of the different Locks (eg. scroll lock, num lockπ> or how to do it. I think it is some sort of Bios or Dos service??π> Any help would be greatly appreciated.ππThe easiest way is to access BIOS memory at address 40h:17hππ}πProcedure TestKeys;ππVarπ Scroll_Lock,π Caps_Lock,π Num_Lock,π Ins,π Alt,π Ctrl,π Left_Shift,π Right_Shift : Boolean;π Bios_Keys : Byte Absolute $40:$17;ππbeginπ Ins := ((Bios_Keys And $80) = $80);π Caps_Lock := ((Bios_Keys And $40) = $40);π Num_Lock := ((Bios_Keys And $20) = $20);π Scroll_Lock := ((Bios_Keys And $10) = $10);π Alt := ((Bios_Keys And $8) = $8);π Ctrl := ((Bios_Keys And $4) = $4);π Left_Shift := ((Bios_Keys And $2) = $2);π Right_Shift := ((Bios_Keys And $1) = $1);ππ Writeln('Insert : ', Ins);π Writeln('CapsLock : ', Caps_Lock);π Writeln('NumLock : ', Num_Lock);π Writeln('ScrollLock : ', Scroll_Lock);π Writeln('Alt : ', Alt);π Writeln('Control : ', Ctrl);π Writeln('Left Shift : ', Left_Shift);π Writeln('Right Shift : ', Right_Shift);πend;ππbeginπ TestKeys;π Readln;πend. 13 05-28-9313:49ALL SWAG SUPPORT TEAM Read CTL/ALT/SHIFT #2 IMPORT 8 Uses Dos;πVarπ regs : Registers;π stat : Byte;π inse, caps, numl, scrll, alt, ctrl, lshift, rshift : Boolean;π { declaration of all the bools hidden :) }πbeginπ regs.ah:=2; intr($16,regs);π stat:=regs.al;ππ inSE := stat and 128 <> 0; { Insert on }π CAPS := stat and 64 <> 0; { CapsLock }π NUML := stat and 32 <> 0; { NumLock }π SCRLL := stat and 16 <> 0; { ScrolLock }π ALT := stat and 8 <> 0; { ALT pressed }π CTRL := stat and 4 <> 0; { CTRL pressed }π LSHifT := stat and 2 <> 0; { left Shift " }π RSHifT := stat and 1 <> 0; { right Shift" }ππ Writeln(inSE);π Writeln(CAPS);π Writeln(NUML);π Writeln(SCRLL);π Writeln(ALT);π Writeln(CTRL);π Writeln(LSHifT);π Writeln(RSHifT);πend.π 14 05-28-9313:49ALL SWAG SUPPORT TEAM Read Keyboard STATE Keys IMPORT 17 {π>Can someone give me some code to make the lights Num lock/capsπ>lock/scroll lock keys to turn on?π}ππProgram KeySet;πConstπ CapsState = $40; { Mask For Caps Lock state }π NumState = $20; { Mask For Num Lock state }π ScrollState = $10; { Mask For Scroll Lock state }πVarπ Kb : Byte Absolute $0040:$0017; { Address of keyboard flags }π I : Byte;π S : String;πbeginπ if ParamCount = 0 thenπ beginπ WriteLn;π WriteLn(' Command line options:');π WriteLn;π WriteLn(' C toggle Cap lock state');π WriteLn(' N toggle Num lock state');π WriteLn(' S toggle Scroll lock state');π WriteLn(' Add + to turn on and - to turn off');π Halt(1);π end;π For I := 1 to ParamCount Doπ beginπ S := ParamStr(I);π S[1] := UpCase(S[1]);π { toggle Caps Lock }π if S = 'C' then Kb := Kb xor CapsState;π { toggle Num Lock }π if S = 'N' then Kb := Kb xor NumState;π { toggle Scroll Lock }π if S = 'S' then Kb := Kb xor ScrollState;π { Set Caps Lock on }π if S = 'C+' then Kb := Kb or CapsState;π { Set Num Lock on }π if S = 'N+' then Kb := Kb or NumState;π { Set Scroll Lock on }π if S = 'S+' then Kb := Kb or ScrollState;π { Set Caps Lock off }π if S = 'C-' then Kb := Kb and not (CapsState or not Kb);π { Set Num Lock off }π if S = 'N-' then Kb := Kb and not (NumState or not Kb);π { Set Scroll Lock off }π if S = 'S-' then Kb := Kb and not (ScrollState or not Kb);π end;ππ Write('Caps Lock : ');π if (Kb and CapsState) = CapsState thenπ WriteLn('ON')π elseπ WriteLn('ofF');ππ Write('Num Lock : ');π if (Kb and NumState) = NumState thenπ WriteLn('ON')π elseπ WriteLn('ofF');ππ Write('Scroll Lock: ');π if (Kb and ScrollState) = ScrollState thenπ WriteLn('ON')π elseπ WriteLn('ofF');πend.ππ{πThis Program will toggle, Turn on, or Turn off the Caps Lock, NumπLock, and Scroll Lock lights. and when its done it tells you theπstate of each key.π}π 15 05-28-9313:49ALL SWAG SUPPORT TEAM Keyboard SCAN Keys IMPORT 86 {AM▒Hi everyone, I have a question. I need to know if there is some simpleπAM▒way to do the following. I want to pass as a parameter to a ProcedureπAM▒that will indicate what keypresses are valid. I am doing this alreadyπAM▒for regular keys, but I need to be able to list regular keys as well asπAM▒extended key(mostly Function keys).ππAM▒I do like so,ππAM▒Command_Keys : Set of Char ['Q', 'A', 'K'];πAM▒Is there a way to add extended keys to the above.ππDeclare extended scan codes, then format them into an Array:π}πConstππ(* Function keys *)π F1 = $3B00; ShF1 = $5400; CtrlF1 = $5E00; AltF1 = $6800;π F2 = $3C00; ShF2 = $5500; CtrlF2 = $5F00; AltF2 = $6900;π F3 = $3D00; ShF3 = $5600; CtrlF3 = $6000; AltF3 = $6A00;π F4 = $3E00; ShF4 = $5700; CtrlF4 = $6100; AltF4 = $6B00;π F5 = $3F00; ShF5 = $5800; CtrlF5 = $6200; AltF5 = $6C00;π F6 = $4000; ShF6 = $5900; CtrlF6 = $6300; AltF6 = $6D00;π F7 = $4100; ShF7 = $5A00; CtrlF7 = $6400; AltF7 = $6E00;π F8 = $4200; ShF8 = $5B00; CtrlF8 = $6500; AltF8 = $6F00;π F9 = $4300; ShF9 = $5C00; CtrlF9 = $6600; AltF9 = $7000;π F10 = $4400; ShF10 = $5D00; CtrlF10 = $6700; AltF10 = $7100;π F11 = $8500; ShF11 = $8700; CtrlF11 = $8900; AltF11 = $8B00;π F12 = $8600; ShF12 = $8800; CtrlF12 = $8A00; AltF12 = $8C00;ππ(* Numeric keypad *)π Up = $4800; ShUp = $4838; CtrlUp = $8D00; AltUp = $9800;π Down = $5000; ShDown = $5032; CtrlDown = $9100; AltDown = $A000;π Left = $4B00; ShLeft = $4B34; CtrlLeft = $7300; AltLeft = $9B00;π Right = $4D00; ShRight = $4D36; CtrlRight = $7400; AltRight = $9D00;π Home = $4700; ShHome = $4737; CtrlHome = $7700; AltHome = $9700;πendKey = $4F00; Shend = $4F31; Ctrlend = $7500; Altend = $9F00;π PgUp = $4900; ShPgUp = $4939; CtrlPgUp = $8400; AltPgUp = $9900;π PgDn = $5100; ShPgDn = $5133; CtrlPgDn = $7600; AltPgDn = $A100;π Ins = $5200; ShIns = $5230; CtrlIns = $9200; AltIns = $A200;π Del = $5300; ShDel = $532E; CtrlDel = $9300; AltDel = $A300;π Pad5 = $4C00; ShPad5 = $4C35; CtrlPad5 = $8F00; AltPad5 = $9C00;ππ(* Alphabetic keys *)π LowA = $1E61; UpA = $1E41; CtrlA = $1E01; AltA = $1E00;π LowB = $3062; UpB = $3042; CtrlB = $3002; AltB = $3000;π LowC = $2E63; UpC = $2E43; CtrlC = $2E03; AltC = $2E00;π LowD = $2064; UpD = $2044; CtrlD = $2004; AltD = $2000;π LowE = $1265; UpE = $1245; CtrlE = $1205; AltE = $1200;π LowF = $2166; UpF = $2146; CtrlF = $2106; AltF = $2100;π LowG = $2267; UpG = $2247; CtrlG = $2207; AltG = $2200;π LowH = $2368; UpH = $2348; CtrlH = $2308; AltH = $2300;π LowI = $1769; UpI = $1749; CtrlI = $1709; AltI = $1700;π LowJ = $246A; UpJ = $244A; CtrlJ = $240A; AltJ = $2400;π LowK = $256B; UpK = $254B; CtrlK = $250B; AltK = $2500;π LowL = $266C; UpL = $264C; CtrlL = $260C; AltL = $2600;π LowM = $326D; UpM = $324D; CtrlM = $320D; AltM = $3200;π LowN = $316E; UpN = $314E; CtrlN = $310E; AltN = $3100;π LowO = $186F; UpO = $184F; CtrlO = $180F; AltO = $1800;π LowP = $1970; UpP = $1950; CtrlP = $1910; AltP = $1900;π LowQ = $1071; UpQ = $1051; CtrlQ = $1011; AltQ = $1000;π LowR = $1372; UpR = $1352; CtrlR = $1312; AltR = $1300;π LowS = $1F73; UpS = $1F53; CtrlS = $1F13; AltS = $1F00;π LowT = $1474; UpT = $1454; CtrlT = $1414; AltT = $1400;π LowU = $1675; UpU = $1655; CtrlU = $1615; AltU = $1600;π LowV = $2F76; UpV = $2F56; CtrlV = $2F16; AltV = $2F00;π LowW = $1177; UpW = $1157; CtrlW = $1117; AltW = $1100;π LowX = $2D78; UpX = $2D58; CtrlX = $2D18; AltX = $2D00;π LowY = $1579; UpY = $1559; CtrlY = $1519; AltY = $1500;π LowZ = $2C7A; UpZ = $2C5A; CtrlZ = $2C1A; AltZ = $2C00;ππ(* Number keys, on top row of keyboard *)π Num1 = $0231; Alt1 = $7800;π Num2 = $0332; Ctrl2 = $0300; Alt2 = $7900;π Num3 = $0433; Alt3 = $7A00;π Num4 = $0534; Alt4 = $7B00;π Num5 = $0635; Alt5 = $7C00;π Num6 = $0736; Ctrl6 = $071E; Alt6 = $7D00;π Num7 = $0837; Alt7 = $7E00;π Num8 = $0938; Alt8 = $7F00;π Num9 = $0A39; Alt9 = $8000;π Num0 = $0B30; Alt0 = $8100;ππ(* Miscellaneous *)π Space = $3920;π BkSp = $0E08; CtrlBkSp = $0E7F; AltBkSp = $0E00;π Tab = $0F09; ShTab = $0F00; CtrlTab = $9400; AltTab = $A500;π Enter = $1C0D; CtrlEnter= $1C0A; AltEnter = $1C00;π Esc = $011B; AltEsc = $0100;ππ Minus = $0C2D; CtrlMinus = $0C1F; AltMinus = $8200;π Plus = $0D2B; AltPlus = $8300;πPadMinus = $4A2D; CtrlPadMinus = $8E00; AltPadMinus= $4A00;π PadPlus = $4E2B; CtrlPadPlus = $9000; AltPadPlus = $4E00;π Star = $092A;π PadStar = $372A; AltPadStar = $3700;ππ{AM>I do like so,πAM>Command_Keys : Set of Char ['Q', 'A', 'K'];π >Is there a way to add extended keys to the above.ππ Hi Andrew!π One painless way is to set the high bit For Function keys.π}πUses Crt;πConstπ Home = #199; UArr = #200; PgUp = #201;π LArr = #203; Five = #204; RArr = #205;π endkey = #207; DArr = #208; PgDn = #209;π Ins = #210; Del = #211;ππ CtrlHome = #247; CtrlUP = #141; CtrlPgUp = #138;π CtrlLArr = #243; CtrlFive = #143; CtrlRArr = #244;π Ctrlend = #245; CtrlDown = #145; CtrlPgDn = #246;π CtrlIns = #146; CtrlDel = #147;ππ BackSp = #8;π Tab = #9; STab = #143;π Enter = #13;π Esc = #27;ππ CtrlPrtsc = #242;ππ CtrlA = #1; AltA = #158; Alt1 = #248;π CtrlB = #2; AltB = #176; Alt2 = #249;π CtrlC = #3; AltC = #174; Alt3 = #250;π CtrlD = #4; AltD = #160; Alt4 = #251;π CtrlE = #5; AltE = #146; Alt5 = #252;π CtrlF = #6; AltF = #161; Alt6 = #253;π CtrlG = #7; AltG = #162; Alt7 = #254;π CtrlH = #8; AltH = #163; Alt8 = #255;π CtrlI = #9; AltI = #151; Alt9 = #134;π CtrlJ = #10; AltJ = #164; Alt0 = #135;π CtrlK = #11; AltK = #165; Altminus = #136;π CtrlL = #12; AltL = #166; Altequals = #137;π CtrlM = #13; AltM = #178;π CtrlN = #14; AltN = #177;π CtrlO = #15; AltO = #152;π CtrlP = #16; AltP = #153;π CtrlQ = #17; AltQ = #144;π CtrlR = #18; AltR = #147;π CtrlS = #19; AltS = #159;π CtrlT = #20; AltT = #148;π CtrlU = #21; AltU = #150;π CtrlV = #22; AltV = #175;π CtrlW = #23; AltW = #145;π CtrlX = #24; AltX = #173;π CtrlY = #25; AltY = #149;π CtrlZ = #26; AltZ = #172;ππ F1 = #187; sF1 = #212; CtrlF1 = #222; AltF1 = #232;π F2 = #188; sF2 = #213; CtrlF2 = #223; AltF2 = #233;π F3 = #189; sF3 = #214; CtrlF3 = #224; AltF3 = #234;π F4 = #190; sF4 = #215; CtrlF4 = #225; AltF4 = #235;π F5 = #191; sF5 = #216; CtrlF5 = #226; AltF5 = #236;π F6 = #192; sF6 = #217; CtrlF6 = #227; AltF6 = #237;π F7 = #193; sF7 = #218; CtrlF7 = #228; AltF7 = #238;π F8 = #194; sF8 = #219; CtrlF8 = #229; AltF8 = #239;π F9 = #195; sF9 = #220; CtrlF9 = #230; AltF9 = #240;π F10 = #196; sF10 = #221; CtrlF10 = #231; AltF10 = #241;π F11 = #139; sF11 = #141; CtrlF11 = #154; AltF11 = #156;π F12 = #140; sF12 = #142; CtrlF12 = #155; AltF12 = #157;ππ Key : Char = #0;ππVarπ NextOn : ^Word Absolute $0040:$001A; {keyboard buffer}π NextOff : ^Word Absolute $0040:$001C; {keyboard buffer}π KeyStatusBits : Word Absolute $0040:$0017; {keyboard buffer}π KeyStatus : Recordπ RShift, LShift,π RCtrl, LCtrl,π RAlt, LAlt,π Caps, CapsON,π Ins, InsON,π Scroll, ScrlON,π Num, NumON : Boolean;π end;ππProcedure GetKeyStatus; { Changes KeyStatus Variable }πConst Old : Word = 0;πbeginπ Old := KeyStatusBits;π FillChar(KeyStatus,SizeOf(KeyStatus),0);π With KeyStatus doπ beginπ RShift := ((Old Shr 0 ) and 1) = 1;π LShift := ((Old Shr 1 ) and 1) = 1;π RCtrl := ((Old Shr 2 ) and 1) = 1; { Test For either CTRL Key }π RAlt := ((Old Shr 3 ) and 1) = 1; { Test For either Alt Key }π ScrlON := ((Old Shr 4 ) and 1) = 1; { Is Scroll Lock light on }π NumON := ((Old Shr 5 ) and 1) = 1; { Is Num Lock light on }π CapsON := ((Old Shr 6 ) and 1) = 1; { Is Caps Lock light on }π InsON := ((Old Shr 7 ) and 1) = 1; { Is Insert State on }π LCtrl := ((Old Shr 8 ) and 1) = 1; { This also sets bit 3 }π LAlt := ((Old Shr 9 ) and 1) = 1; { This also sets bit 4 }π Scroll := ((Old Shr 12) and 1) = 1; { This toggles bit 5 }π Num := ((Old Shr 13) and 1) = 1; { This toggles bit 6 }π Caps := ((Old Shr 14) and 1) = 1; { This toggles bit 7 }π Ins := ((Old Shr 15) and 1) = 1; { This toggles bit 8 }π end;πend; { }ππFunction GetKey : Char;πbeginπ If KeyPressed then { Test For BIOS key pressed }π beginπ Key := ReadKey; { Basic BIOS Keyboard Entry }π if Key = #0 thenπ beginπ Key := ReadKey;π Inc(Key,128); { Make Expanded key codes one Byte }π end; { }π end else Key := #0;π GetKey := Key;πend; { }ππProcedure FlushBuffer;πbeginπ Move(NextOn,NextOff,SizeOf(NextOn));πend; { }ππVar test : Char ;πbeginπ ClrScr;π WriteLN('Press Both Shift Keys to end');π Repeatπ GetKeyStatus;π Test := GetKey;π if Test <> #0 Then Write(Test);ππ Until (KeyStatus.RShift and KeyStatus.LShift);πend.π 16 05-28-9313:49ALL SWAG SUPPORT TEAM Keyboard SCAN Codes IMPORT 16 {πROBERT ROTHENBURGππ>I have created a Menu Bar, Now I think key #77 is left and key #77 isπ>assigned to "M" or one of them. But anyway so when someone pushes theπ>"M" key the menu bar moves. So how can I stop this, I only want it toπ>use the arrow keys and a few letters but not "M".ππYou guessed it: USE BIOS CALLS!π}ππProgram ShowCodes; {* This Program will output the keyboardπ {* scan codes. Use the Function "ScanCode"π {* in your Program once you know the codesπ {* For each keypress *}πUsesπ Crt, Dos;ππFunction Byte2Hex(numb : Byte): String; { Converts Byte to hex String }πConstπ HexChars : Array[0..15] of Char = '0123456789ABCDEF';πbeginπ Byte2Hex[0] := #2;π Byte2Hex[1] := HexChars[numb shr 4];π Byte2Hex[2] := HexChars[numb and 15];πend; { Byte2Hex }ππFunction Numb2Hex(numb : Word): String; { Converts Word to hex String.}πbeginπ Numb2Hex := Byte2Hex(hi(numb)) + Byte2Hex(lo(numb));πend; { Numb2Hex }ππFunction ScanCode : Word;πVarπ reg : Registers; {* You need the Dos Unit For this! *}πbeginπ reg.AH := $10; {* This should WAIT For a keystroke. Ifπ {* you'd like to POLL For a keystroke andπ {* have your Program do other stuff Whileπ {* "waiting" For a key-stroke change toπ {* reg.AH:=$11 instead... *}π intr($16, reg);π ScanCode := reg.AX {* The high-Byte is the "scan code" *}πend; {* The low-Byte is the ASCII Character *}ππbeginπ Repeatπ Writeln(Numb2Hex(ScanCode) : 6)π Until False; {* You'll have to reboot after running this <g>*}πend.ππ{πI "think" the arrow-key scan codes are:ππ $4800 = Up Arrowπ $5000 = Down Arrowπ $4B00 = Left Arrowπ $4D00 = Right Arrowπ}π 17 05-28-9313:49ALL SWAG SUPPORT TEAM Display MAKE/BREAK codes IMPORT 14 PROGRAM ScanCode ; { display MAKE and BREAK scan codes }ππUSES Crt, Dos, KeyIntr ; { keyboard interrupt support }ππ{ ----- this program will probably hang a debugger ----- }ππVarπ OldInt09 : Pointer ;π ExitSave : Pointer ;ππ{$F+} Procedure RestoreInt09 ;πBeginπ ExitProc := ExitSave ;π SetIntVec( $09, OldInt09 ) ;πEnd ;ππ{$F+} Procedure NewInt09 ; Interrupt ; { return scan code as key's value }πVarπ ScanCode : Byte ;π BufferFull : Boolean ;ππBeginπ EnableInterrupts ;π ScanCode := ReadScanCode ;π ResetKeyboard ;π BufferFull := Not StoreKey( ScanCode, ScanCode ) ;π EOI ;π If BufferFull thenπ Beginπ Sound( 880 ) ;π Delay( 100 ) ;π Sound( 440 ) ;π Delay( 100 ) ;π NoSound ;π End ;π { variation : move the EOI before the beep to after it }π { note the difference when the keyboard overflows }πEnd ;ππ{ see Turbo Pascal 5.0 reference p 450 for a list of scan codes }π{ 6.0 programmers guide p 354 }ππVarπ N : Byte ;ππBEGINπ ExitSave := ExitProc ;π ExitProc := @RestoreInt09 ;π GetIntVec( $09, OldInt09 ) ;π SetIntVec( $09, @NewInt09 ) ;ππ WriteLn( ' Display "make" and "break" scan codes ' ) ;π WriteLn ;π WriteLn( ' Hit the <Esc> key to exit ' ) ;π Repeatπ Delay( 400 ) ; { make it easy to overrun keyboard }π N := Ord( ReadKey ) ; { n is the scan code from NewInt09 }π If N < 128 thenπ WriteLn( 'Make ', n )π Elseπ WriteLn( ' Break ', n - 128 ) ;π Until n = 1 ; { the make code for Esc }πEND.π 18 05-28-9313:49ALL SWAG SUPPORT TEAM Extended Keys IMPORT 28 { MICHAEL NICOLAI }ππUsesπ Dos;ππFunction Get_Extended_KeyCode : Word;πVarπ regs : Registers;πbeginπ regs.ah := $10;π intr($16, regs);π Get_Extended_KeyCode := (regs.ah shl 4) + regs.al;πend;ππ{πThis Function waits Until a key is pressed. The upper Byte contains theπscan code, the lower Byte contains the ASCII code. If you don't want yourπProgram to hang if no key is pressed, use this funtion to check if anyπkeycode is actually present in the keyboard buffer:π}ππFunction Check_For_Extended_KeyStroke : Boolean; { like KeyPressed }πVarπ regs : Registers;πbeginπ regs.ah := $11;π intr($16, regs);π Check_For_Extended_Keystroke := False;π if ((regs.flags and fzero) = 0) thenπ Check_For_Extended_Keystroke := True;πend;ππ{πAfter this Function returns True, the keycode can be read Withπ'Get_Extended_KeyCode'.ππHere are the routines my Functions are based on:ππINTERRUPT 16h - Function 10hπKeyboard - Get enhanced keystrokeππPurpose: Wait For any keyboard input.πAvailable on: AT or PS/2 With enhanced keyboard support only.πRestrictions: none.πRegisters at call: AH = 10h.πReturn Registers: AH = scan code, AL = ASCII codeπDetails: if no keystroke is available, this Function waits Until one isπ placed in the keyboard buffer. Unlike Function 00h, this Functionπ does not discard extended keystrokes.πConflicts: none known.πππINTERRUPT 16h - Function 11hπKeyboard - Check For enhanced keystrokeππPurpose: Checks For availability of any keyboard input.πAvailable on: AT or PS/2 With enhanced keyboard only.πRestrictions: none.πRegisters at call: AH = 11hπReturn Registers: ZF set if no keystroke availableπ ZF clear if keystroke availableπ AH = scan codeπ AL = ASCII codeπDetails: if a keystroke is available, it is not removed from the keyboardπ buffer. Unlike Function 01h, this Function does not discard extendedπ keystrokes.πconflicts: none known.πππINTERRUPT 16h - Function 12hπKeyboard - Get extended shift statesππPurpose: Returns all shift-flags information from enhanced keyboards.πAvailable: AT or PS/2 With enhanced keyboard only.πRestrictions: none.πRegisters at call: AH = 12hπReturn Registers: AL = shift flags 1 (same as returned by Function 02h):π bit 7: Insert activeπ 6: CapsLock activeπ 5: NumLock activeπ 4: ScrollLock activeπ 3: Alt key pressed (either Alt on 101/102-keyπ keyboard)π 2: Crtl key pressed (either Ctrl on 101/102-keyπ keyboard)π 1: left shift key pressedπ 0: right shift key pressedππ AH = shift flags 2:π bit 7: SysRq key pressedπ 6: CapsLock pressedπ 5: NumLock pressedπ 4: ScrollLock pressedπ 3: right Alt key prssedπ 2: right Ctrl key pressedπ 1: left Alt key pressedπ 0: left Ctrl key pressedπDetails: AL bit 3 is set only For left Alt key on many machines. AH bits 7π through 4 are always clear on a Compaq SLT/286.πConflicts: none known.π}π 19 05-28-9313:49ALL SWAG SUPPORT TEAM Trap CTRL-BREAK IMPORT 13 { >> What sort of code do I need to include in a pascal Program (Writen inπ >> Borland Pascal 6.0) to disable CTRL-BREAK and CTRL-C?π}πUnit CAD;ππInterfaceππUses Dos;ππVarπ Int9Handler : Pointer;ππProcedure InterceptCtrlAltDel;πProcedure RestoreCAD;ππ ImplementationππProcedure InterceptCtrlAltDel; Assembler;ππConstπ Ctrl = 4;π Alt = 8;π Del = $53;π KbdPort = $60; { Keyboard port }π KbdCtrlPort = $61; { Keyboard control port }π PIC = $20; { 8259 Interrupt controller }π EOI = $20; { end-of-interrupt }ππ Asmππ PUSH AXπ PUSH DSπ MOV AX, SEG @Dataπ MOV DS, AXπ STIπ in AL, KbdPortπ and AL, 01111111bπ CMP AL, Delπ JNE @2ππ @1 : MOV AH, 2 { BIOS Get keyboard flags service }π inT 16hπ TEST AL, Ctrl + Altπ JNZ @3ππ @2 : PUSHFπ CALL [Int9Handler]π JMP @4ππ @3 : in AL, KbdCtrlPortπ MOV AH, ALπ or AL, 10000000bπ OUT KbdCtrlPort, ALπ XCHG AH, ALπ OUT KbdCtrlPort, ALπ CLIππ MOV AL, EOIπ OUT PIC, ALπ @4 : POP DSπ POP AXπ IRET { make sure we return correctly }πend; { InterceptCtrlAltDel }ππProcedure RestoreCAD;ππbeginπ SETinTVEC (9, Int9Handler);πend; { RestoreCAD }πππbeginπ GETinTVEC (9, Int9Handler);π SETinTVEC (9, @InterceptCtrlAltDel);πend. {Unit CAD}ππ 20 05-28-9313:49ALL SWAG SUPPORT TEAM Trap CTRL-BREAK #2 IMPORT 19 {Here is my solution to the problem of trapping Ctrl-Alt-Del. As extra suger,πI'm providing hooks to make this Program TSR. Happy hacking!ππ<<File: trapboot.pas>>ππ{$m 1024,0,0} { Necesarry if you want to make the Program resident. }π{****************************************************************************}π{* NoBoot *}π{* *}π{* This Program stops rebooting While it is running by trapping *}π{* Ctrl-Alt-Del. *}π{* *}π{----------------------------------------------------------------------------}ππUsesπ Dos, Crt;ππVarπ OldKBVec : Pointer;ππ{ Declare all Variables in our interrupt routine global so that no stack }π{ allocation of Variables will be done during the interrupt. }πVarπ Regs : Registers;π temp : Byte;π KBflag1: Byte Absolute $40:$17;ππProcedure MyKB; inTERRUPT;πConstπ EOI = $20;π KB_DATA = $60;π KB_CTL = $61;π inT_CTL = $20;π DEL_sc = $53; { Scancode of the del key }ππbeginπ { Check if Alt and Ctrl are pressed }π if ((KBFlag1 and 4)=4) and ((KBFlag1 and 8)=8) andπ (Port[KB_DATA]= DEL_sc) then begin { get scancode of pressed key }ππ { The following four lines signals that the key is read and that the }π { hardware interrupt is over. }π temp:=Port[Kb_CTL];π Port[KB_CTL]:= temp or $80;π Port[KB_CTL]:= temp;π Port[inT_CTL]:= EOI;ππ { Don't do ANYTHinG here that requires BIOS. This 'Writeln' is using the }π { Crt Unit. }π Writeln('Ouch! That hurts!'); { Show we are here and alive! }π endπ else beginπ intr($69, Regs); { Call the old interrupt routine }π end;πend;ππVarπ Ch : Char;ππbeginπ GetIntVec($9, OldKBVec);π SetIntVec($69, OldKBVec);π SetIntVec($9, @MyKB);ππ { Keep(0); } { Uncomment and erase the rest of the lines to make this Program}ππ Repeatπ Writeln('Press escape to Exit. or Ctrl-Alt-Del if you want...');π ch:= ReadKey;π Until ch=#27;ππ { Forgetting the next line will very surely crash your Computer. }π SetIntVec($9, OldKbVec);πend.π 21 05-28-9313:49ALL SWAG SUPPORT TEAM Trap PAUSE Key IMPORT 10 {The problem is that the pause key actually paUses the Computerπvia hardware. to reset the pause, you can use the timer interruptπto generate a reset process at every tick. The method hereπwas taken from some Computer magazine.π}ππProgram TrapPause;πUses Dos;πVarπ Timerint : Pointer;π PauseFlag : Boolean;ππProcedure PauseDetect(flags,CS,IP,AX,BX,CX,DX,SI,DI,DS,ES,BP: Word);π {This latches on to the system timer interrupt to detect if theπ pause key has been pressed, and if so to reset the system to allowπ operation to continue and to set Pauseflag = True}π interrupt;π beginπ if memw[$0:$418] and 8 = 8 then {Test bit 3}π beginπ Pauseflag := True;π memw[$0:$418] := memw[$0:$418] and $F7; {Set bit 3 = 0}π end;π Inline($9C/ {PushF}π $3E/ {DS}π $FF/$1E/timerint);{Far call to usual timer interrupt}π end;πππbeginπ Getintvec($08,Timerint); {Save old interrupt For timer}π Setintvec($08,@PauseDetect); {Redirect timer to PauseDetect}πend.ππ 22 05-28-9313:49ALL SWAG SUPPORT TEAM Trap PAUSE Key #2 IMPORT 28 {GE> Does anyone know how to disable the pause key?ππ Here's one way, done in Assembly, With example Turbo Pascal code ...π}π(*******************************************************************)π Program TestTrapPause; { demo disabling the Pause key }π Uses Crt, { import CheakBreak, KeyPressed }π Dos; { import GetIntVec, SetIntVec }π Var old09Vector : Pointer; { to hold original ISR }π loopc, { a loop count }π ppress : Word; { counts Pause key presses }π{-------------------------------------------------------------------}π{ the following Procedures|Functions mask & count Pause keystrokes }π Procedure InitTrapPause( oldVector : Pointer ); EXTERNAL;π Procedure TrapPause; Interrupt; EXTERNAL;π Function PausePresses : Word; EXTERNAL;π Procedure ForgetPaUses; EXTERNAL;π {$L NOPAUSE.OBJ} { Assembly, Near calls }π{-------------------------------------------------------------------}π beginπ ClrScr;π CheckBreak := False; { don't allow Ctrl-Break }ππ GetIntVec( 9, old09Vector ); { get current keyboard ISR }π InitTrapPause( old09Vector ); { pass vector to TrapPause }π SetIntVec( 9, @TrapPause ); { enable TrapPause ISR }π ForgetPaUses; { zero the PausePresses counter }ππ loopc := 0; { initialize }π WriteLn; WriteLn( 'Press the PAUSE key... ');ππ Repeatπ WriteLn;π ppress := PausePresses; { initial Pause press count }π While (ppress = PausePresses) and (not KeyPressed)π do beginπ inC( loopc ); if (loopc = 65535) then loopc := 0;π Write( loopc:5, ' you''ve pressed the Pause key ' );π Write( ppress, ' times',#13 );π end; {While}π Until KeyPressed;ππ SetIntVec( 9, old09Vector ); { restore Pause & release ISR }ππ end {TestTrapPause}.π(*******************************************************************)ππ{ The following TP Program will create NOPAUSE.ARC, which containsπ NOPAUSE.OBJ ...ππ Program A; Var G:File; Const V:Array [ 1..279 ] of Byte =(π26,8,78,79,80,65,85,83,69,46,79,66,74,0,94,248,0,0,0,43,26,67,140,78,π194,29,1,0,0,12,128,26,0,88,224,230,13,156,48,117,230,148,113,17,100,π74,19,47,150,14,0,0,64,96,200,19,34,69,136,96,146,136,162,13,0,1,2,2,π28,131,4,32,200,196,0,12,140,60,145,114,164,8,21,40,65,170,76,41,50,165,π204,68,6,48,101,22,129,34,133,230,204,41,96,38,54,72,226,36,9,21,42,82,π130,64,201,57,115,34,128,4,72,149,50,45,226,99,34,9,68,4,38,138,10,16,π13,84,28,0,1,38,46,226,102,99,209,17,1,46,70,77,44,123,132,64,218,137,π46,142,25,112,10,64,88,214,33,6,243,200,73,115,6,13,29,16,49,114,228,π144,1,226,136,156,50,103,222,200,201,3,98,138,11,43,124,221,148,65,200,π134,14,167,125,80,200,129,225,81,132,206,1,44,157,92,252,115,1,247,223,π92,0,176,64,152,3,1,250,25,0,72,6,92,132,154,56,44,238,105,218,125,56,π201,0,64,12,1,216,0,90,120,67,248,205,133,119,133,223,94,120,51,249,29,π(96 min left), (H)elp, More? 156,88,20,228,188,197,64,39,134,6,58,43,69,2,38,210,1,26,0);π begin Assign(G,'NOPAUSE.ARC'); ReWrite(G,Sizeof(V));π BlockWrite(G,V,1); Close(G); end (*Gbug1.5*).π}π 23 05-29-9308:53ALL SWAG SUPPORT TEAM Various READ Key/Chars IMPORT 19 {πAuthor : GAYLE DAVISππI have seen a number of messages recently about keyboard access. Here areπsome neat FAST routines to use instead of ReadKey (Crt Unit). Be advisedπthat in these routines, I add 128 to the HI Byte in order to be able to useπall 256 Characters. Just remember to add 128 to test For all Function keys.π}ππUsesπ Dos;ππFunction GetKey (Var Key : Word) : Boolean; Assembler;π{ determine if key pressed and return it as a Word }π{ if Lo(key) = 0 and Hi(key) <> 0 then we have a FN key ! }πAsmπ MOV AH, 1π INT 16Hπ MOV AL, 0π JE @@1π xor AH, AHπ INT 16Hπ LES DI, Keyπ MOV Word PTR ES : [DI], AXπ MOV AL, 1π @@1 :πend;ππFunction GetChar (Var Key : Char) : Boolean;π{ determine if key pressed and return it as a Char}πVarπ c : Word;πbeginπ Key := #0;π if GetKey (c) thenπ beginπ GetChar := True;π if (LO (c) = 0) and (HI (c) <> 0) thenπ Key := CHR ( HI (c) + 128 ) { add 128 For FN keys }π elseπ Key := CHR (LO (c) );π endπ elseπ GetChar := False;πend;ππFunction KeyReady : Char;π{ looks For and PEEKS at Char but DOES not read it out of buffer }π{ returns the Char it finds or #0 if no Character waiting }πVarπ Regs : Registers;π Key : Byte;πbeginπ Regs.AH := 1; { determine if a key has been }π INTR ( $16, Regs ); { converted to a key code }π if ( Regs.Flags and FZERO = 0 ) thenπ begin { yes, Character now in keyboard buffer }π { determine what it is }π if ( Regs.AL = 0 ) thenπ Key := Regs.AH + 128π elseπ Key := Regs.AL;π endπ elseπ Key := 0;π KeyReady := CHR (Key);πend;ππProcedure ClearKeyBuffer;πVarπ Regs : Registers;πbeginπ Regs.AH := 0; { Clear ENTIRE keyboard }π INTR ( $16, Regs ); { buffer via the BIOS }πend;ππFunction AnyKeyPressed (Ch : Char; Clear : Boolean) : Boolean;π{ Check if a Character is present in buffer, and optionally clears it }πVarπ Key : Char;π Regs : Registers;ππbeginπ Key := KeyReady;π AnyKeyPressed := (Key = Ch);π if (Key = Ch) and Clear thenπ ClearKeyBuffer;πend;π